/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package avl.sv.shared.XML;

import avl.sv.shared.Annotations.Annotation;
import avl.sv.shared.Annotations.Attributes;
import avl.sv.shared.Annotations.ROI;
import java.awt.Polygon;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 *
 * @author benbryan
 */
public class AperioAnnotationXML_Writer {

    public static String getXMLString(ArrayList<Annotation> annos) {
        
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
      
        try {
            DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            // root elements
            Document doc = docBuilder.newDocument();
            
            Element annotationsNode = doc.createElement("Annotations");
            annotationsNode.setAttribute("MicronsPerPixel", "1"  );
            doc.appendChild(annotationsNode);
            
            AperioAnnotationXML_Writer.appendAnnotations( doc, annos, annotationsNode);
            
            // write the content into xml file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            
            // Output to console for testing
            StreamResult result = new StreamResult(bos);
            transformer.transform(source, result);

        } catch (TransformerException | ParserConfigurationException ex) {
            Logger.getLogger(SolutionXML_Writer.class.getName()).log(Level.SEVERE, null, ex);
        } 
        
        return bos.toString();
    }
    
    protected static void appendAnnotations(Document doc, ArrayList<Annotation> annos, Element annotationsNode) {       
        for (Annotation anno : annos) {
            Element annotationNode = createAnnotationElement(doc, anno);
            annotationsNode.appendChild(annotationNode);
        }
    }
    
    protected static Element createAnnotationElement(Document doc, Annotation anno) {     
            Element annotationNode = doc.createElement("Annotation");
            
            String visible = (anno.visible) ? "1" : "0";
            String selected = (anno.selected) ? "1" : "0";

            annotationNode.setAttribute("Id", String.valueOf(anno.id)  );
            annotationNode.setAttribute("Name", anno.name );
            annotationNode.setAttribute("Type", String.valueOf(anno.type) );
            annotationNode.setAttribute("LineColor", String.valueOf((long)Math.abs(anno.lineColor)) );
            annotationNode.setAttribute("Visible", visible );
            annotationNode.setAttribute("Selected", selected );
            
            annotationNode.setAttribute("ReadOnly", "0"  );
            annotationNode.setAttribute("NameReadOnly", "0"  );
            annotationNode.setAttribute("LineColorReadOnly", "0"  );
            annotationNode.setAttribute("Incremental", "0"  );
            annotationNode.setAttribute("MarkupImagePath", ""  );
            annotationNode.setAttribute("MacroName", ""  );
            
            appendAnnotationAttributes(doc, anno, annotationNode);
            
            appendRegions(doc, anno.getRois(), annotationNode);
            appendPlots(doc, anno.getRois(), annotationNode);
            return annotationNode;
    }  

    protected static void appendRegionAttributeHeaders(Document doc, Element annotationNode) {
        Element regionsNode = doc.createElement("RegionAttributeHeaders");
        annotationNode.appendChild(regionsNode);
        Element attributeHeaderNode;
        
        attributeHeaderNode = doc.createElement("AttributeHeader");
        attributeHeaderNode.setAttribute("Id", "9999");
        attributeHeaderNode.setAttribute("Name", "Region");
        attributeHeaderNode.setAttribute("ColumnWidth", "-1");
        regionsNode.appendChild(attributeHeaderNode);

        attributeHeaderNode = doc.createElement("AttributeHeader");
        attributeHeaderNode.setAttribute("Id", "9997");
        attributeHeaderNode.setAttribute("Name", "Length");
        attributeHeaderNode.setAttribute("ColumnWidth", "-1");
        regionsNode.appendChild(attributeHeaderNode);
        
        attributeHeaderNode = doc.createElement("AttributeHeader");
        attributeHeaderNode.setAttribute("Id", "9996");
        attributeHeaderNode.setAttribute("Name", "Area");
        attributeHeaderNode.setAttribute("ColumnWidth", "-1");
        regionsNode.appendChild(attributeHeaderNode);
        
        attributeHeaderNode = doc.createElement("AttributeHeader");
        attributeHeaderNode.setAttribute("Id", "9998");
        attributeHeaderNode.setAttribute("Name", "Text");
        attributeHeaderNode.setAttribute("ColumnWidth", "-1");
        regionsNode.appendChild(attributeHeaderNode);
        
        attributeHeaderNode = doc.createElement("AttributeHeader");
        attributeHeaderNode.setAttribute("Id", "1");
        attributeHeaderNode.setAttribute("Name", "Description");
        attributeHeaderNode.setAttribute("ColumnWidth", "-1");
        regionsNode.appendChild(attributeHeaderNode);
    }
    
    
    protected static void appendRegions(Document doc, ArrayList<ROI> rois, Element annotationNode) {
        int roiID = 0;
        Element regionsNode = doc.createElement("Regions");
        annotationNode.appendChild(regionsNode);
        appendRegionAttributeHeaders(doc, regionsNode);

        for (ROI r : rois) {
            String selected = (r.selected) ? "1" : "0";
            String negativeROA = (r.negativeROA) ? "1" : "0";
            String analyze = (r.analyze) ? "1" : "0";
            String type = String.valueOf(r.getType());
            
            Element regionNode = doc.createElement("Region");
            regionsNode.appendChild(regionNode);
            
            regionNode.setAttribute( "Id", String.valueOf(roiID));
            regionNode.setAttribute( "Type", type);
            regionNode.setAttribute( "Selected", selected );
            regionNode.setAttribute( "Text", r.text );
            regionNode.setAttribute( "NegativeROA", negativeROA );
            regionNode.setAttribute( "Analyze", analyze );
                       
            regionNode.setAttribute("Zoom", "0.015650");
            regionNode.setAttribute("ImageLocation", "");
            regionNode.setAttribute("ImageFocus", "0");
            regionNode.setAttribute("Length", "0");
            regionNode.setAttribute("Area", "0");
            regionNode.setAttribute("LengthMicrons", "0");
            regionNode.setAttribute("AreaMicrons", "0");
            regionNode.setAttribute("InputRegionId", "0");
            regionNode.setAttribute("DisplayId", "1");

            appendRegionAttributes(doc, r, regionNode);
            appendVertices(doc, r.getPolygon(), regionNode);
            roiID++;
        }
    }

    protected static void appendPlots(Document doc, ArrayList<ROI> rois, Element annotationNode) {
        Element plotsNode = doc.createElement("Plots");
        annotationNode.appendChild(plotsNode);
    }
    
    protected static void appendVertices(Document doc, Polygon p, Element regionNode) {
        int x[] = p.xpoints;
        int y[] = p.ypoints;
        Element verticesNode = doc.createElement("Vertices");
        regionNode.appendChild(verticesNode);
        for (int i = 0; i < p.npoints; i++) {
            Element vertexNode = doc.createElement("Vertex");    
            verticesNode.appendChild(vertexNode);
            vertexNode.setAttribute( "X", String.valueOf(x[i]));
            vertexNode.setAttribute( "Y", String.valueOf(y[i]));
        }
    }

    protected static void appendAnnotationAttributes(Document doc, Annotation anno, Element annotationNode) {
        Element regionsNode = doc.createElement("Attributes");
        annotationNode.appendChild(regionsNode);
        Element attributeNode = doc.createElement("Attribute");
        regionsNode.appendChild(attributeNode);
        attributeNode.setAttribute( "Name", "Description");
        attributeNode.setAttribute( "Id", "0");
        attributeNode.setAttribute( "Value", "");
    }
    
    protected static void appendRegionAttributes(Document doc, ROI r, Element regionNode) {
        Element attributesNode = doc.createElement("Attributes");
        regionNode.appendChild(attributesNode);
        for (Attributes a : r.attributes) {
            Element attributeNode = doc.createElement("Attribute");
            attributesNode.appendChild(attributeNode);
            attributeNode.setAttribute( "Name", a.name);
            attributeNode.setAttribute( "Id", String.valueOf(a.id));
            attributeNode.setAttribute( "Value", a.value);
        }
    }
    
}
